package com.pcbly.web.components.utils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.pcbly.web.components.utils.property.OfficeGlobals;




@SuppressWarnings("unchecked")
public final class ClassUtilsStatic {
	private static final Logger log = LogManager
			.getLogger(ClassUtilsStatic.class);

	private static ClassUtilsStatic instance = new ClassUtilsStatic();
	protected boolean propertiesLoaded;

	public static Class forName(String className) throws ClassNotFoundException {
		return loadClass(className);
	}

	public static void propertiesLoaded() {
		instance.propertiesLoaded = true;
	}

	public static Object newInstance(String className)
			throws ClassNotFoundException, IllegalAccessException,
			InstantiationException {
		return forName(className).newInstance();
	}

	public static InputStream getResourceAsStream(String name) {
		return instance.loadResource(name);
	}

	public static ResourceBundle getBundle(String name, Locale locale) {
		return instance.loadBundle(name, locale);
	}

	public static ResourceBundle getBundle(String name) {
		return instance.loadBundle(name, OfficeGlobals.getLocale());
	}

	private ClassUtilsStatic() {
	}

	// private Class loadClass(String className) throws ClassNotFoundException {
	// List dirs = getDirs();
	// if (dirs.isEmpty())
	// return loadNormalClass(className);
	// String regex = OfficeGlobals
	// .getOfficeProperty(RELOADING_CLASSLOADER_REGEX);
	// if (regex != null && className.matches(regex)) {
	// log.warn((new StringBuilder()).append("(Re)loading class ").append(
	// className).toString());
	// return loadReloadingClass(className, dirs);
	// } else {
	// return loadNormalClass(className);
	// }
	// }

	private InputStream loadResource(String name) {
		InputStream in = getClass().getResourceAsStream(name);
		if (in == null) {
			in = Thread.currentThread().getContextClassLoader()
					.getResourceAsStream(name);
			if (in == null)
				in = getClass().getClassLoader().getResourceAsStream(name);
		}
		return in;
	}

	private ResourceBundle loadBundle(String name, Locale locale) {
		ResourceBundle bundle = null;
		try {
			bundle = ResourceBundle.getBundle(name, locale);
		} catch (Exception e) {
		}
		if (bundle == null) {
			ClassLoader loader = Thread.currentThread().getContextClassLoader();
			try {
				bundle = ResourceBundle.getBundle(name, locale, loader);
			} catch (Exception e) {
			}
		}
		return bundle;
	}

	public static Class loadClass(String className, Class callingClass)
			throws ClassNotFoundException {
		try {
			return Thread.currentThread().getContextClassLoader().loadClass(
					className);
		} catch (ClassNotFoundException e) {
			try {
				return Class.forName(className);
			} catch (ClassNotFoundException ex) {
				return callingClass.getClassLoader().loadClass(className);
			}
		}
	}

	public static URL getResource(String resourceName, Class callingClass) {
		URL url = Thread.currentThread().getContextClassLoader().getResource(
				resourceName);
		if (url == null)
			url = callingClass.getClassLoader().getResource(resourceName);
		return url;
	}

	public static InputStream getResourceAsStream(String resourceName,
			Class callingClass) {
		try {
			URL url = getResource(resourceName, callingClass);
			return url == null ? null : url.openStream();
		} catch (IOException e) {
			return null;
		}
	}

	public static Class getImplementationClass(Class interfaceClass) {
		return null;
	}

	public static byte[] readStream(InputStream in, int size)
			throws IOException {
		if (in == null)
			return null;
		if (size == 0)
			return new byte[0];
		int currentTotal = 0;
		int bytesRead;
		byte data[];
		for (data = new byte[size]; currentTotal < data.length
				&& (bytesRead = in.read(data, currentTotal, data.length
						- currentTotal)) >= 0; currentTotal += bytesRead)
			;
		in.close();
		return data;
	}

	private static Class loadClass(String className)
			throws ClassNotFoundException {
		log
				.debug("\u4ECE\u5B57\u7B26\u4E32\u8868\u793A\u7684\u7C7B\u540D\u88C5\u8F7DClass["
						+ className + "]");
		return Class.forName(className);
	}

	public static Object loadObject(String className) throws Exception {
		log
				.debug("\u4ECE\u5B57\u7B26\u4E32\u8868\u793A\u7684\u7C7B\u540D\u88C5\u8F7D\u5BF9\u8C61["
						+ className + "]");
		Class classResult = loadClass(className);
		Object ObjResult = classResult.newInstance();
		return ObjResult;
	}

	public static Constructor getClassConstructor(String className,
			Class paramTypes[]) throws Exception {
		Class classResult = Class.forName(className);
		Constructor con = classResult.getConstructor(paramTypes);
		return con;
	}

	public static Constructor[] getClassConstructors(String className)
			throws Exception {
		Class classResult = Class.forName(className);
		Constructor con[] = classResult.getConstructors();
		return con;
	}

	public static boolean isPublicAccessibleField(Class clazz, String fieldName) {
		log
				.debug("\u5224\u65AD\u7C7B["
						+ clazz.getName()
						+ "]\u7684field["
						+ fieldName
						+ "]\u662F\u5426\u4E3A\u516C\u5171\u3001\u53EF\u8BBF\u95EE\u7684");
		try {
			clazz.getField(fieldName);
		} catch (SecurityException e) {
			return false;
		} catch (NoSuchFieldException e) {
			return false;
		}
		return true;
	}

	private static Class getSuperClass(Class clazz) {
		log
				.debug("\u83B7\u5F97\u7C7B" + clazz.getName()
						+ "\u7684\u7236\u7C7B");
		return clazz.getSuperclass();
	}

	public static Field getPublicFieldOfClass(Class clazz, String fieldName)
			throws SecurityException, ClassNotFoundException,
			NoSuchFieldException {
		log.debug("\u5C1D\u8BD5\u83B7\u5F97\u7C7B[" + clazz.getName()
				+ "]\u7684public\u7C7B\u578BField[" + fieldName
				+ "]\u7C7B\u5BF9\u8C61");
		if (isPublicAccessibleField(clazz, fieldName))
			return clazz.getField(fieldName);
		else
			return null;
	}

	public static Field[] getPublicFieldsOfClass(Class clazz) throws Exception {
		log.debug("\u5C1D\u8BD5\u83B7\u5F97\u7C7B[" + clazz.getName()
				+ "]\u7684\u6240\u6709public\u7C7B\u578BFields");
		Field f[] = clazz.getFields();
		return f;
	}

	public static Field[] getDeclaredFieldsOfClass(Class clazz)
			throws Exception {
		log.debug("\u5C1D\u8BD5\u83B7\u5F97\u7C7B[" + clazz.getName()
				+ "]\u7684\u6240\u6709\u58F0\u660E\u7684Fields");
		Class c = clazz;
		List fList = new ArrayList();
		for (; !c.getName().equalsIgnoreCase("java.lang.Object"); c = getSuperClass(c)) {
			Field f[] = c.getDeclaredFields();
			if (f != null && f.length > 0) {
				for (int i = 0; i < f.length; i++)
					fList.add(f[i]);

			}
			log.debug("\u5C1D\u8BD5\u8BBF\u95EE\u7C7B[" + c.getName()
					+ "]\u7684\u7236\u7C7B");
		}

		Field result[] = new Field[fList.size()];
		for (int i = 0; i < fList.size(); i++)
			result[i] = (Field) fList.get(i);

		return result;
	}

	public static void setPublicFieldOfObject(Object obj, String fieldName,
			Object fieldValue) throws Exception {
		log.debug("\u5C1D\u8BD5\u8BBE\u7F6E\u5BF9\u8C61["
				+ obj.getClass().getName() + "]\u7684field[" + fieldName
				+ "]\u4E3A" + fieldValue.toString());
		Field f = getPublicFieldOfClass(obj.getClass(), fieldName);
		f.set(obj, fieldValue);
	}

	private static String getMethodModifierString(int modifier) {
		StringBuffer sb = new StringBuffer();
		if (Modifier.isPrivate(modifier))
			sb.append("private ");
		if (Modifier.isPublic(modifier))
			sb.append("public ");
		if (Modifier.isProtected(modifier))
			sb.append("protected ");
		if (Modifier.isStatic(modifier))
			sb.append("static ");
		if (Modifier.isAbstract(modifier))
			sb.append("abstract ");
		if (Modifier.isNative(modifier))
			sb.append("native ");
		if (Modifier.isSynchronized(modifier))
			sb.append("synchronized ");
		return sb.toString();
	}

	private static String getClassString(Class clazzes[]) {
		if (clazzes != null) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < clazzes.length; i++) {
				sb.append(clazzes[i].getName());
				if (i < clazzes.length - 1)
					sb.append(",");
			}

			return sb.toString();
		} else {
			return "";
		}
	}

	private static String getMethodParamTypesString(Class clazzes[]) {
		return getClassString(clazzes);
	}

	private static String getMethodExceptionTypesString(Class clazzes[]) {
		return getClassString(clazzes);
	}

	private static String getMethodSignature(Method method) {
		StringBuffer sb = new StringBuffer();
		sb.append(getMethodModifierString(method.getModifiers()));
		sb.append(method.getReturnType().getName());
		sb.append(" ");
		sb.append(method.getName());
		sb.append("(");
		sb.append(getMethodParamTypesString(method.getParameterTypes()));
		sb.append(")");
		if (method.getExceptionTypes() != null
				&& method.getExceptionTypes().length > 0) {
			sb.append(" throws");
			sb
					.append(getMethodExceptionTypesString(method
							.getExceptionTypes()));
		}
		return sb.toString();
	}

	public static Method findMatchedPublicMethod(Class clazz,
			String methodName, Class methodParamTypes[]) {
		log.debug("\u5C1D\u8BD5\u67E5\u627E\u7C7B\u5BF9\u8C61["
				+ clazz.getName() + "]\u7684\u516C\u5171\u65B9\u6CD5["
				+ methodName + "("
				+ getMethodParamTypesString(methodParamTypes) + ")]");
		Method methods[] = clazz.getMethods();
		for (int i = 0; i < methods.length; i++)
			if (compareMethodWithMethodNameAndMethodParamTypes(methods[i],
					methodName, methodParamTypes, true)) {
				log.debug("\u8FD4\u56DE\u7C7B\u5BF9\u8C61[" + clazz.getName()
						+ "]\u7684\u516C\u5171\u65B9\u6CD5\uFF1A"
						+ getMethodSignature(methods[i]));
				return methods[i];
			}

		log.debug("\u672A\u53D1\u73B0\u7C7B\u5BF9\u8C61[" + clazz.getName()
				+ "]\u7684\u516C\u5171\u65B9\u6CD5[" + methodName + "]");
		return null;
	}

	public static Method findMatchedPublicMethod(Class clazz, String methodName) {
		log.debug("\u5C1D\u8BD5\u67E5\u627E\u7C7B\u5BF9\u8C61["
				+ clazz.getName() + "]\u7684\u516C\u5171\u65B9\u6CD5["
				+ methodName + "]");
		Method methods[] = clazz.getMethods();
		for (int i = 0; i < methods.length; i++)
			if (compareMethodWithMethodNameAndMethodParamTypes(methods[i],
					methodName, null, false)) {
				log.debug("\u8FD4\u56DE\u7C7B\u5BF9\u8C61[" + clazz.getName()
						+ "]\u7684\u516C\u5171\u65B9\u6CD5\uFF1A"
						+ getMethodSignature(methods[i]));
				return methods[i];
			}

		log.debug("\u672A\u53D1\u73B0\u7C7B\u5BF9\u8C61[" + clazz.getName()
				+ "]\u7684\u516C\u5171\u65B9\u6CD5[" + methodName + "]");
		return null;
	}

	public static Method[] getClassPublicMethods(Class clazz) throws Exception {
		log.debug("\u5C1D\u8BD5\u67E5\u627E\u7C7B\u5BF9\u8C61["
				+ clazz.getName()
				+ "]\u7684\u6240\u6709\u516C\u5171\u65B9\u6CD5");
		Method method[] = clazz.getMethods();
		return method;
	}

	public static Method findMatchedDeclaredMethod(Class clazz,
			String methodName) {
		Class c = clazz;
		log.debug("\u67E5\u627E\u7C7B[" + c.getName()
				+ "]\u58F0\u660E\u7684\u65B9\u6CD5[" + methodName + "]");
		for (; !c.getName().equalsIgnoreCase("java.lang.Object"); c = getSuperClass(c)) {
			for (int i = 0; i < c.getDeclaredMethods().length; i++)
				if (compareMethodWithMethodNameAndMethodParamTypes(c
						.getDeclaredMethods()[i], methodName, null, false)) {
					log.debug("\u8FD4\u56DE\u7C7B\u5BF9\u8C61["
							+ clazz.getName()
							+ "]\u58F0\u660E\u7684\u65B9\u6CD5\uFF1A"
							+ getMethodSignature(c.getDeclaredMethods()[i]));
					return c.getDeclaredMethods()[i];
				}

		}

		log.debug("\u672A\u53D1\u73B0\u7C7B\u5BF9\u8C61[" + clazz.getName()
				+ "]\u58F0\u660E\u7684\u65B9\u6CD5[" + methodName + "]");
		return null;
	}

	private static boolean compareMethodWithMethodNameAndMethodParamTypes(
			Method method, String methodName, Class methodParamTypes[],
			boolean needMatchParamTypes) {
		if (method.getName().equalsIgnoreCase(methodName)) {
			if (needMatchParamTypes)
				return TypeTransformOp.compareClassArray(method
						.getParameterTypes(), methodParamTypes);
			else
				return true;
		} else {
			log.debug("\u65B9\u6CD5\u540D\u4E0D\u5339\u914D\uFF1A"
					+ method.getName() + "," + methodName);
			return false;
		}
	}

	public static Method findMatchedDeclaredMethodLightly(Class clazz,
			String methodName) {
		Class c = clazz;
		log.debug("\u67E5\u627E\u7C7B[" + c.getName()
				+ "]\u58F0\u660E\u7684\u65B9\u6CD5[" + methodName + "]");
		for (; !c.getName().equalsIgnoreCase("java.lang.Object"); c = getSuperClass(c)) {
			for (int i = 0; i < c.getDeclaredMethods().length; i++)
				if (c.getDeclaredMethods()[i].getName().equalsIgnoreCase(
						methodName)) {
					log.debug("\u8FD4\u56DE\u7C7B\u5BF9\u8C61["
							+ clazz.getName()
							+ "]\u58F0\u660E\u7684\u65B9\u6CD5\uFF1A"
							+ getMethodSignature(c.getDeclaredMethods()[i]));
					return c.getDeclaredMethods()[i];
				}

		}

		log.debug("\u672A\u53D1\u73B0\u7C7B\u5BF9\u8C61[" + clazz.getName()
				+ "]\u58F0\u660E\u7684\u65B9\u6CD5[" + methodName + "]");
		return null;
	}

	public static Method findMatchedDeclaredMethod(Class clazz,
			String methodName, Class methodParamTypes[]) {
		Class c = clazz;
		log.debug("\u67E5\u627E\u7C7B[" + c.getName()
				+ "]\u58F0\u660E\u7684\u65B9\u6CD5[" + methodName + "("
				+ getMethodParamTypesString(methodParamTypes) + ")]");
		for (; !c.getName().equalsIgnoreCase("java.lang.Object"); c = getSuperClass(c)) {
			for (int i = 0; i < c.getDeclaredMethods().length; i++)
				if (compareMethodWithMethodNameAndMethodParamTypes(c
						.getDeclaredMethods()[i], methodName, methodParamTypes,
						true)) {
					log.debug("\u8FD4\u56DE\u7C7B\u5BF9\u8C61["
							+ clazz.getName()
							+ "]\u58F0\u660E\u7684\u65B9\u6CD5\uFF1A"
							+ getMethodSignature(c.getDeclaredMethods()[i]));
					return c.getDeclaredMethods()[i];
				}

		}

		log.debug("\u672A\u53D1\u73B0\u7C7B\u5BF9\u8C61[" + clazz.getName()
				+ "]\u58F0\u660E\u7684\u65B9\u6CD5[" + methodName + "("
				+ getMethodParamTypesString(methodParamTypes) + ")]");
		return null;
	}

	public static Method[] getClassDeclaredMethods(Class clazz) {
		Class c = clazz;
		log.debug("\u67E5\u627E\u4E0E\u7C7B[" + c.getName()
				+ "]\u58F0\u660E\u7684\u65B9\u6CD5");
		List mList = new ArrayList();
		for (; !c.getName().equalsIgnoreCase("java.lang.Object"); c = getSuperClass(c)) {
			for (int i = 0; i < c.getDeclaredMethods().length; i++) {
				log.debug("\u8FD4\u56DE\u7C7B\u5BF9\u8C61[" + clazz.getName()
						+ "]\u58F0\u660E\u7684\u65B9\u6CD5\uFF1A"
						+ getMethodSignature(c.getDeclaredMethods()[i]));
				mList.add(c.getDeclaredMethods()[i]);
			}

			log.debug("\u5C1D\u8BD5\u8BBF\u95EE\u7C7B[" + c.getName()
					+ "]\u7684\u7236\u7C7B");
		}

		Method result[] = new Method[mList.size()];
		for (int i = 0; i < mList.size(); i++)
			result[i] = (Method) mList.get(i);

		return result;
	}

	public static Object invokeStaticMethod(Class clazz, String methodName,
			String paramType[], String paramValue[]) throws Exception {
		log.debug("\u8C03\u7528\u7C7B[" + clazz.getName()
				+ "]\u4E2D\u7684\u9759\u6001\u65B9\u6CD5[" + methodName + "]");
		Class paramClazzes[] = new Class[0];
		Object paramObjects[] = new Object[0];
		if (paramType != null) {
			paramClazzes = TypeTransformOp.loadClasses(paramType);
			paramObjects = TypeTransformOp.loadObjects(paramType, paramValue);
		}
		return findMatchedDeclaredMethod(clazz, methodName, paramClazzes)
				.invoke(clazz, paramObjects);
	}

	public static Object invokeMethod(Object obj, String methodName,
			String paramType[], String paramValue[], boolean needInstantObject)
			throws Exception {
		log.debug("\u8C03\u7528\u7C7B[" + obj.getClass().getName()
				+ "]\u4E2D\u7684\u975E\u9759\u6001/\u9759\u6001\u65B9\u6CD5["
				+ methodName + "]");
		if (needInstantObject)
			obj = loadObject(obj.getClass().getName());
		Class paramClazzes[] = new Class[0];
		Object paramObjects[] = new Object[0];
		if (paramType == null) {
			return findMatchedDeclaredMethod(obj.getClass(), methodName,
					paramClazzes).invoke(obj, paramObjects);
		} else {
			paramClazzes = TypeTransformOp.loadClasses(paramType);
			paramObjects = TypeTransformOp.loadObjects(paramType, paramValue);
			return findMatchedDeclaredMethod(obj.getClass(), methodName,
					paramClazzes).invoke(obj, paramObjects);
		}
	}

	public static void printArray(Object objArray[]) {
		log.debug("\u6253\u5370\u6570\u7EC4");
		for (int i = 0; i < objArray.length; i++)
			System.out.println(objArray[i].toString());

	}

	public static void printList(List objList) {
		log.debug("\u6253\u5370\u5217\u8868");
		for (int i = 0; i < objList.size(); i++)
			System.out.println(objList.get(i).toString());

	}

	public static String List2String(List objList, String newLine) {
		log.debug("\u6253\u5370\u5217\u8868");
		StringBuffer result = new StringBuffer();
		for (int i = 0; i < objList.size(); i++)
			result.append((String) objList.get(i)).append(newLine);

		return result.toString();
	}

	public static String printHttpRequestParameters(HttpServletRequest request) {
		log.debug("\u6253\u5370HttpRequest\u53C2\u6570");
		Set keySet = request.getParameterMap().keySet();
		if (keySet != null && keySet.size() > 0) {
			Iterator iter = keySet.iterator();
			StringBuffer result = new StringBuffer();
			String key;
			String keyValue;
			for (; iter.hasNext(); result.append(key).append("=").append(
					keyValue).append("\n")) {
				key = (String) iter.next();
				keyValue = request.getParameterValues(key)[0];
			}

			return result.toString();
		} else {
			return null;
		}
	}

	public static String beanToString(Object beanObj) throws Exception {
		log.debug("\u6253\u5370\u5C06bean[" + beanObj.getClass().getName()
				+ "]\u8F6C\u6362\u4E3A\u5B57\u7B26\u4E32\n");
		StringBuffer result = (new StringBuffer("bean ClassName=")).append(
				beanObj.getClass().getName()).append("\n");
		Field fieldArray[] = getDeclaredFieldsOfClass(beanObj.getClass());
		for (int i = 0; i < fieldArray.length; i++) {
			Field f = fieldArray[i];
			String methonName = "get" + f.getName();
			Object callResult = invokeMethod(beanObj, methonName, null, null,
					false);
			result.append(f.getName()).append("'s Value=").append(
					callResult.toString()).append("\n");
		}

		return result.toString();
	}

	public static void printBean(Object beanObj) throws Exception {
		log.debug("\u6253\u5370bean[" + beanObj.getClass().getName() + "]");
		System.out.println(beanToString(beanObj));
	}

	public static void printBeanList(List objList) throws Exception {
		log.debug("\u6253\u5370bean\u5217\u8868");
		for (int i = 0; i < objList.size(); i++)
			printBean(objList.get(i));

	}

	public static void printMap(Map map) {
		log.debug("\u6253\u5370Map");
		Object keyName;
		for (Iterator it = map.keySet().iterator(); it.hasNext(); log
				.debug("\u4E3B\u952E[" + keyName + "]=" + map.get(keyName)))
			keyName = it.next();

	}

	private static boolean compareObject(Object obj01, Object obj02,
			int compareType) {
		switch (compareType) {
		case 0: // '\0'
			return obj01.getClass().equals(obj02.getClass());

		case 1: // '\001'
			return TypeTransformOp.ObjectToString(obj01).equals(
					TypeTransformOp.ObjectToString(obj02));

		case 2: // '\002'
			return obj01 == obj02;

		case 3: // '\003'
			if (obj01 == null && obj02 == null)
				return true;
			return obj01 != null && obj02 != null;
		}
		return false;
	}

	public static boolean compareBean(Object beanObj01, Object beanObj02)
			throws Exception {
		log.debug("\u6BD4\u8F83\u4E24\u4E2Abean\u4E2D\u6570\u636E");
		Field fieldArray[] = getDeclaredFieldsOfClass(beanObj01.getClass());
		for (int i = 0; i < fieldArray.length; i++) {
			Field f = fieldArray[i];
			String methonName = "get"
					+ f.getName().substring(0, 1).toUpperCase()
					+ f.getName().substring(1).toLowerCase();
			Object fieldValue01 = invokeMethod(beanObj01, methonName, null,
					null, false);
			Object fieldValue02 = invokeMethod(beanObj02, methonName, null,
					null, false);
			log.debug("\u6BD4\u8F83\u503C\u57DF:" + f.getName() + " "
					+ fieldValue01 + "," + fieldValue02);
			if (compareObject(fieldValue01, fieldValue02, 3)) {
				if (fieldValue01 != null || fieldValue02 != null) {
					if (!fieldValue01.getClass().isPrimitive()
							&& !fieldValue02.getClass().isPrimitive()) {
						if (!compareObject(fieldValue01, fieldValue02, 0)) {
							log.debug("There is difference:");
							log.debug("Object01 Field:" + f.getName()
									+ "'s class=" + fieldValue01.getClass());
							log.debug("Object02 Field:" + f.getName()
									+ "'s class=" + fieldValue02.getClass());
							return false;
						}
					} else if (fieldValue01.getClass().isPrimitive()
							&& fieldValue02.getClass().isPrimitive()
							&& !compareObject(fieldValue01, fieldValue02, 2)) {
						log.debug("There is difference:");
						log.debug("Object01 Field:" + f.getName() + "'s value="
								+ fieldValue01);
						log.debug("Object02 Field:" + f.getName() + "'s value="
								+ fieldValue02);
						return false;
					}
					if (!compareObject(fieldValue01, fieldValue02, 1)) {
						log.debug("There is difference:");
						log.debug("Object01 Field:" + f.getName() + "'s value="
								+ TypeTransformOp.ObjectToString(fieldValue01));
						log.debug("Object02 Field:" + f.getName() + "'s value="
								+ TypeTransformOp.ObjectToString(fieldValue02));
						return false;
					}
				}
			} else {
				log.debug("There is difference:");
				log.debug("Object01 Field:" + f.getName() + "'s value="
						+ fieldValue01);
				log.debug("Object02 Field:" + f.getName() + "'s value="
						+ fieldValue02);
				return false;
			}
		}

		return true;
	}

	private static String getCleanerFieldName(String fakeFieldName,
			String fieldNamePrefix) {
		if (fieldNamePrefix != null && fieldNamePrefix.length() > 0)
			return fakeFieldName.substring(fieldNamePrefix.length());
		else
			return fakeFieldName;
	}

	public static String getBeanFieldStringValueWithPrefixFieldName(
			Object beanObj, String fieldName, String fieldNamePrefix)
			throws Exception {
		String fName = getCleanerFieldName(fieldName, fieldNamePrefix);
		log.debug("\u8C03\u7528bean[" + beanObj.getClass().getName()
				+ "]\u7684get\u65B9\u6CD5\u83B7\u5F97bean\u7684\u6210\u5458["
				+ fName + "]\u503C\u7684\u5B57\u7B26\u4E32\u5F62\u5F0F");
		Object obj = invokeMethod(beanObj, "get" + fName, null, null, false);
		return TypeTransformOp.ObjectToString(obj);
	}

	public static void setBeanFieldStringValueWithPrefixFieldName(
			Object beanObj, String fieldName, String fieldNamePrefix,
			String fieldValue) throws Exception {
		String fName = getCleanerFieldName(fieldName, fieldNamePrefix);
		log.debug("\u8C03\u7528bean[" + beanObj.getClass().getName()
				+ "]\u7684set\u65B9\u6CD5\u8BBE\u7F6Ebean\u7684\u6210\u5458["
				+ fName + "]\u503C\u4E3A" + fieldValue);
		Method method = findMatchedDeclaredMethod(beanObj.getClass(), "set"
				+ fName);
		if (method != null) {
			if (method.getParameterTypes().length == 1) {
				String paramValue[] = new String[1];
				paramValue[0] = fieldValue;
				Object paramObjects[] = TypeTransformOp.loadObjects(method
						.getParameterTypes(), paramValue);
				method.invoke(beanObj, paramObjects);
			} else {
				log
						.debug("\u6CA1\u6709\u627E\u5230\u5339\u914D\u53C2\u6570\u7684\u65B9\u6CD5:set"
								+ fieldName);
			}
		} else {
			log
					.debug("\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u65B9\u6CD5:set"
							+ fieldName);
		}
	}

	public static String getBeanFieldStringValue(Object beanObj,
			String fieldName) throws Exception {
		return getBeanFieldStringValueWithPrefixFieldName(beanObj, fieldName,
				"");
	}

	public static void setBeanFieldStringValue(Object beanObj,
			String fieldName, String fieldValue) throws Exception {
		setBeanFieldStringValueWithPrefixFieldName(beanObj, fieldName, "",
				fieldValue);
	}

	public static Object getBeanFieldValue(Object beanObj, String fieldName)
			throws Exception {
		log.debug("\u8C03\u7528bean[" + beanObj.getClass().getName()
				+ "]\u7684get\u65B9\u6CD5\u83B7\u5F97bean\u7684\u6210\u5458["
				+ fieldName + "]\u503C");
		Method method = findMatchedDeclaredMethodLightly(beanObj.getClass(),
				"get" + fieldName.substring(0, 1).toUpperCase()
						+ fieldName.substring(1));
		if (method != null) {
			if (method.getParameterTypes().length == 0) {
				return method.invoke(beanObj, new Object(){});
			} else {
				log
						.warn("\u8C03\u7528bean["
								+ beanObj.getClass().getName()
								+ "]\u7684get"
								+ fieldName
								+ "\u65B9\u6CD5\u65F6\u53D1\u73B0\u53C2\u6570\u4E2A\u6570>0");
				return null;
			}
		} else {
			log.warn("\u6CA1\u6709\u627E\u5230bean["
					+ beanObj.getClass().getName() + "]\u7684get" + fieldName
					+ "\u65B9\u6CD5");
			return null;
		}
	}

	public static Object setBeanFieldValue(Object beanObj, String fieldName,
			Object fieldValue) throws Exception {
		log.debug("\u8C03\u7528bean[" + beanObj.getClass().getName()
				+ "]\u7684set\u65B9\u6CD5\u83B7\u5F97bean\u7684\u6210\u5458["
				+ fieldName + "]\u503C");
		Method method = findMatchedDeclaredMethodLightly(beanObj.getClass(),
				"set" + fieldName.substring(0, 1).toUpperCase()
						+ fieldName.substring(1));
		if (method != null) {
			if (method.getParameterTypes().length == 1) {
				Object paramValues[] = new Object[1];
				paramValues[0] = fieldValue;
				method.invoke(beanObj, paramValues);
				return beanObj;
			} else {
				log
						.warn("\u8C03\u7528bean["
								+ beanObj.getClass().getName()
								+ "]\u7684set"
								+ fieldName
								+ "\u65B9\u6CD5\u65F6\u53D1\u73B0\u53C2\u6570\u4E2A\u6570>1");
				return null;
			}
		} else {
			log.warn("\u6CA1\u6709\u627E\u5230bean["
					+ beanObj.getClass().getName() + "]\u7684set" + fieldName
					+ "\u65B9\u6CD5");
			return beanObj;
		}
	}

	public static boolean isChildClass(Class clazz, String parentClassName) {
		for (Class superClass = clazz.getSuperclass(); superClass != null
				&& !superClass.getName().equalsIgnoreCase("java.lang.Object"); superClass = superClass
				.getSuperclass()) {
			log.debug("\u83B7\u5F97\u7236\u7C7B:" + superClass.getName());
			if (superClass.getName().equalsIgnoreCase(parentClassName))
				return true;
		}

		return false;
	}

	public static boolean isClassOrChildClass(Class clazz, String className) {
		for (Class testClass = clazz; testClass != null
				&& !testClass.getName().equalsIgnoreCase("java.lang.Object"); testClass = testClass
				.getSuperclass()) {
			log.debug("\u83B7\u5F97\u7C7B:" + testClass.getName());
			if (testClass.getName().equalsIgnoreCase(className))
				return true;
		}

		return false;
	}

	public static boolean isDeclaredAccessibleField(Class clazz,
			String fieldName) {
		Class c = clazz;
		log
				.debug("\u5224\u65AD\u7C7B["
						+ clazz.getName()
						+ "]\u7684field["
						+ fieldName
						+ "]\u662F\u5426\u4E3A\u88AB\u58F0\u660E\u8FC7\u3001\u53EF\u8BBF\u95EE\u7684");
		if (!c.getName().equalsIgnoreCase("java.lang.Object")) {
			try {
				c.getDeclaredField(fieldName);
				return true;
			} catch (NoSuchFieldException nsf_ex) {
				try {
					c = getSuperClass(c);
					log
							.debug("\u5224\u65AD\u7C7B["
									+ clazz.getName()
									+ "]\u7684\u7236\u7C7B["
									+ c.getName()
									+ "]\u7684field["
									+ fieldName
									+ "]\u662F\u5426\u4E3A\u88AB\u58F0\u660E\u8FC7\u3001\u53EF\u8BBF\u95EE\u7684");
					return true;
				} catch (NullPointerException np_ex) {
					return false;
				}
			}
		}
		return false;
	}

	public static Field getDeclaredFieldOfClass(Class clazz, String fieldName) {

		log.debug("\u5C1D\u8BD5\u83B7\u5F97\u7C7B[" + clazz.getName()
				+ "]\u7684\u58F0\u660E\u7684Field[" + fieldName
				+ "]\u7C7B\u5BF9\u8C61");
		if (!isDeclaredAccessibleField(clazz, fieldName))
			return null;
		Class c = clazz;
		if (!c.getName().equalsIgnoreCase("java.lang.Object")) {
			try {
				Field f = c.getDeclaredField(fieldName);
				if (f != null)
					return f;

				c = getSuperClass(c);
			} catch (NoSuchFieldException noSuchFieldEx) {
				c = getSuperClass(c);
			} catch (SecurityException securityEx) {
				return null;
			}
		}
		return null;
	}

	public static Object copyBeanFieldValuesToAnOtherBean(Object bean01,
			Object bean02) throws Exception {
		Field bean01Fields[] = getDeclaredFieldsOfClass(bean01.getClass());
		for (int i = 0; i < bean01Fields.length; i++)
			if (isDeclaredAccessibleField(bean02.getClass(), bean01Fields[i]
					.getName()))
				if (bean01Fields[i].getType().equals(
						getDeclaredFieldOfClass(bean02.getClass(),
								bean01Fields[i].getName()).getType()))
					try {
						setBeanFieldValue(bean02, bean01Fields[i].getName(),
								getBeanFieldValue(bean01, bean01Fields[i]
										.getName()));
					} catch (Exception e) {
						log
								.warn("\u5C06bean01["
										+ bean01.getClass().getName()
										+ "]\u7684\u503C\u57DF\u5B57\u6BB5["
										+ bean01Fields[i].getName()
										+ "]"
										+ "\u8D4B\u503C\u7ED9bean02["
										+ bean01.getClass().getName()
										+ "]\u7684\u76F8\u5E94\u503C\u57DF\u5B57\u6BB5\u53D1\u751F\u9519\u8BEF\uFF1A"
										+ e.getMessage());
					}
				else
					try {
						setBeanFieldStringValue(bean02, bean01Fields[i]
								.getName(), getBeanFieldStringValue(bean01,
								bean01Fields[i].getName()));
					} catch (Exception e) {
						log
								.warn("\u5C06bean01["
										+ bean01.getClass().getName()
										+ "]\u7684\u503C\u57DF\u5B57\u6BB5["
										+ bean01Fields[i].getName()
										+ "]\u7684\u5B57\u7B26\u4E32\u5F62\u5F0F"
										+ "\u503C\u8D4B\u503C\u7ED9bean02["
										+ bean01.getClass().getName()
										+ "]\u7684\u76F8\u5E94\u503C\u57DF\u5B57\u6BB5\u53D1\u751F\u9519\u8BEF\uFF1A"
										+ e.getMessage());
					}

		return bean02;
	}
}
